﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

namespace TypeBuilderFx.Core
{
    /// <summary>Component caching dynamic types.</summary>
    /// <remarks>Can safely be used in multi-threading.</remarks>
    public class DiskTypeEmitterCache : TypeEmitterCacheBase
    {
        private readonly ModuleBuilderExtender _moduleBuilder;

        /// <summary>Constructor.</summary>
        /// <param name="doWriteAssembly">
        /// Defines if the assembly where the types will be built is going to be written to disk or just in memory.
        /// </param>
        /// <param name="assemblyName">Name of the assembly</param>
        public DiskTypeEmitterCache(string assemblyName)
        {
            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                new AssemblyName(assemblyName),
                AssemblyBuilderAccess.RunAndSave);

            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName, assemblyName + ".dll", true);

            _moduleBuilder = new ModuleBuilderExtender(moduleBuilder);
        }

        /// <summary>Returns a module builder written to disk.</summary>
        protected override ModuleBuilderExtender ModuleBuilder
        {
            get { return _moduleBuilder; }
        }

        protected override void OnDispose()
        {
            AssemblyBuilder assemblyBuilder = (AssemblyBuilder)_moduleBuilder.ModuleBuilder.Assembly;

            assemblyBuilder.Save(assemblyBuilder.GetName().Name + ".dll");
        }
    }
}